package uts.sdk.modules.kuxAbortSignal
import java.util.concurrent.atomic.AtomicBoolean
import kotlinx.coroutines.*
import io.dcloud.uts.*

class KuxAbortSignal: IKuxAbortSignal {
    private val listeners = mutableMapOf<String, MutableSet<() -> Unit>>()
	private val _aborted = AtomicBoolean(false)
	var reason: Any? = null
		private set // 外部只读，内部可修改
	
	val aborted: Boolean
	    get() = _aborted.get()

    override fun addEventListener(eventName: String, listener: () -> Unit) {
        listeners.getOrPut(eventName, { mutableSetOf() }).add(listener)
		if (aborted && eventName == "abort") listener()
    }
	
	override fun removeEventListener(eventName: String, listener: () -> Unit) {
        listeners[eventName]?.remove(listener)
    }
	
	internal fun triggerAbort(reason: Any? = null) {
		if (_aborted.compareAndSet(false, true)) {
			this.reason = reason
			listeners["abort"]?.forEach { it.invoke() }
			listeners.clear()
		}
	}
	
	companion object {
		fun timeout(ms: Long, reason: Any? = "Timeout"): KuxAbortSignal {
			val signal = KuxAbortSignal()
			GlobalScope.launch {
				delay(ms)
				signal.triggerAbort(reason)
			}
			return signal
		}
	}
}

class KuxAbortController: IKuxAbortController {
	val signal = KuxAbortSignal()
	
	override fun abort(reason: Any? = null) {
		signal.triggerAbort(reason)
	}
}